package com.kingsoft.dc.khaos.module.spark.util

import org.apache.hadoop.fs.{FSDataOutputStream, FileSystem, Path}

import java.io.{BufferedInputStream, ByteArrayInputStream, File, FileInputStream, FileOutputStream, IOException, InputStream, OutputStream}
import sun.misc.BASE64Decoder
import org.apache.hadoop.io.IOUtils
import org.slf4j.{Logger, LoggerFactory}

import scala.io.Source

/**
 * Created by haorenhui on 2020/06/10.
 */
object FileUtils {

  private val LOG: Logger = LoggerFactory.getLogger(this.getClass)

  /**
   * 文件序列化字符串 转换为 序列化数组
   *
   * @param base64Code 文件序列化后的字符串
   */
  def decoderBase64File(base64Code: String): Array[Byte] = {
    var bytes = new Array[Byte](0)
    try
      bytes = new BASE64Decoder().decodeBuffer(base64Code)
    catch {
      case e: IOException =>
        throw new IOException("上传文件的序列化数组字符串转换为序列化数组异常：" + e.getMessage)
    }
    bytes
  }

  /**
   * 将base64字符串解码并保存至文件
   *
   * @param filePath   包含文件名称的path路径
   * @param base64Code 文件序列化后的字符串
   */
  def decoderBase64File(base64Code: String, filePath: String, fs: FileSystem): String = {
    val buffer: Array[Byte] = decoderBase64File(base64Code)
    //保存文件
    saveFile(buffer, filePath, fs)
    filePath
  }

  /**
   * 重载方法，将base64文件写到本地
   */
  def decoderBase64File(base64Code: String, filePath: String): String = {
    val buffer: Array[Byte] = decoderBase64File(base64Code)
    saveFile(buffer, filePath)
    filePath
  }

  def saveFile(buffer: Array[Byte], filePath: String): Unit = {
    try {
      val path = new File(filePath)
      val fileParent = path.getParentFile

      if (!fileParent.exists()) {
        fileParent.mkdirs()
      }

      if (path.exists()) {
        path.delete()
      }

      val output: OutputStream = new FileOutputStream(filePath)
      output.write(buffer)
      output.flush()

      LOG.info(s"$filePath save success")
      output.close()
    } catch {
      case e: Exception =>
        throw new Exception(s"生成文件异常：$e.getMessage")
    }
  }

  /**
   * 将文件对应的字符数组保存为具体文件
   *
   * @param filePath 包含文件名称的path路径
   * @param buffer   文件对应的字符数组
   */
  def saveFile(buffer: Array[Byte], filePath: String, fs: FileSystem): Unit = {
    try {
      LOG.info(s"$filePath save start")
      val inputStream: InputStream = new BufferedInputStream(new ByteArrayInputStream(buffer)) //打开一个BufferedInputStream字节输入流
      //这里是creat()方法表示新创建一个文件，如果想在一个文件上追加，请用append()方法。
      val fsDataOutputStream: FSDataOutputStream = fs.create(new Path(filePath))
      IOUtils.copyBytes(inputStream, fsDataOutputStream, 1024, true)

      fsDataOutputStream.close()
      fs.close()
      LOG.info(s"$filePath save success")
    } catch {
      case e: IOException =>
        throw new IOException("生成文件异常：" + e.getMessage)
    } finally {

    }
  }

  /**
   * 将文件序列化之后的base64字符串保存到文本文件
   *
   * @param base64Code 文件序列化后的字符串
   * @param filePath   包含文件名称的path路径
   */
  def toFile(base64Code: String, filePath: String, fs: FileSystem): Unit = {
    val buffer: Array[Byte] = base64Code.getBytes
    saveFile(buffer, filePath, fs)
  }
}
